//#include "cybertron/core/UtilUrlRequest.hpp"
#include "MasterClient.hpp"
#include "TheApp.hpp"
#include "TaskManager.hpp"
#include"WorkNodeManger.hpp"
#include "cybertron/core/Log.hpp"
#include "cybertron/core/UtilString.hpp"
#include "cybertron/core/UtilFile.hpp"
#include "cybertron/core/UtilStateHelper.hpp"
#include "cybertron/network/Message.hpp"
#include "cybertron/core/UtilSystemResource.hpp"
#include "cybertron/core/ConfigureClient.hpp"
#include "cybertron/core/UtilPath.hpp"
#include "cybertron/core/SimOneEnv.hpp"
#include "cybertron/core/ComputerEnv.hpp"
#include "cybertron/core/UtilWin32.hpp"
#include "cybertron/license/License.hpp"

#include <thread>
#include <fstream>
#ifdef CYBERTRON_LINUX
#include <spawn.h>
#include <stdlib.h> 
#include <sys/types.h>
#include <sys/wait.h>
#endif
#pragma warning(disable:4996)
using namespace cybertron;

MasterClient::MasterClient()
{
	zeroMembers();
}

MasterClient::~MasterClient()
{
	close();
}

void MasterClient::zeroMembers()
{
	mbRunning = true;
	mReconnectCooldown = 1000 * ReconnectSeconds;
	mMasterPort = 0;
	mForceToCoordinatorIp = false;

}

bool MasterClient::cmdOptionExists(const std::string &option)
{
	return std::find(mOptions.begin(), mOptions.end(), option) != mOptions.end();
}

const std::string& MasterClient::getCmdOption(const std::string &option)
{
	std::vector<std::string>::const_iterator itr;
	itr = std::find(mOptions.begin(), mOptions.end(), option);
	if (itr != mOptions.end() && ++itr != mOptions.end()) {
		return *itr;
	}
	static const std::string emptyStr("");
	return emptyStr;
}

bool MasterClient::initialize(/*int argc, char* argv[]*/)
{
	close();
	//recv:
	mMessageRouter.registerHandler(
		Master::ENodeRegisterAtMasterRet,
		[this](Message& msg) {
		onFromMasterNodeRegisterRet(msg);
	});

	mMessageRouter.registerHandler(
		Master::ECommand2AgentFromCommander,
		[this](Message& msg) {
		onFromMasterCommand2Agent(msg);
	});

	mMessageRouter.registerHandler(
		Master::EGetAgentHardwareInfoFromCommander,
		[this](Message& msg) {
		onFromMasterGetAgentHardwareInfo(msg);
	});

	mMessageRouter.registerHandler(
		Master::ETaskReadyRunningToAgent,
		[this](Message& msg) {
		onFromMasterTaskReadyRunning(msg);
	});

	mMessageRouter.registerHandler(
		Master::ETaskStartFromCommander,
		//Agent::ETaskStartFromMaster,
		[this](Message& msg) {
		onFromMasterStartTask(msg);
	});

	mMessageRouter.registerHandler(
		Master::ETaskStopFromCommander,
		[this](Message& msg) {
		onFromMasterStopTask(msg);
	});

	mMessageRouter.registerHandler(
		Master::EWorkNodeStartFromMaster,
		[this](Message& msg) {
		onFromMasterStartWorkNode(msg);
	});

	mMessageRouter.registerHandler(
		Master::EWorkNodeStopFromMaster,
		[this](Message& msg) {
		onFromMasterStopWorkNode(msg);
	});

	mMessageRouter.registerHandler(
		Master::ETaskStateChange,
		[this](Message& msg) {
		onFromTaskStateChange(msg);
	});

	mMessageRouter.registerHandler(
		Common::ESyncWorkNodeDynamicConfig,
		[this](Message& msg) {
		onFromMasterSyncWorkNodeDynamicConfig(msg);
	});

	mMessageRouter.registerHandler(
		Master::EStartScriptFromAgent,
		[this](Message& msg) {
		onFromMasterStartScript(msg);
	});

	mMessageRouter.registerHandler(
		Master::EGetDongleInfoFromAgent,
		[this](Message& msg) {
		onFromMasterGetDongleInfo(msg);
	});

	

	//send:
	//ESyncWorkNodeStatusFromAgent
	//ESyncWorkNodeStateFromAgent
	//ESyncWorkNodeListFromAgent
	//ETaskStartProgressFromAgent
	//EStopTaskFromAgent

	mMasterIp = theApp->getMasterIP();
	mMasterPort = theApp->getMasterPort();

	reconnect();


	return true;
}

void MasterClient::reconnect()
{
	
	if (mpSocketToMasterClient != nullptr)
	{
		mpSocketToMasterClient->close("Close on reconnect");
		mpSocketToMasterClient = nullptr;
	}

	mpSocketToMasterClient = std::make_shared<SocketTcpClient>();
	mpSocketToMasterClient->setHandlerConnected([this]() {
		onConnected();
	});
	mpSocketToMasterClient->setHandlerDisconnected([this]() {
		onDisconnected();
	});
	mpSocketToMasterClient->setHandlerMessage([this](Message& msg) {
		onMessage(msg);
	});

	logInfo("Connecting to master server %s:%d...", mMasterIp.c_str(), mMasterPort);
	while (true)
	{
		bool ok = mpSocketToMasterClient->resolverName(mMasterIp.c_str(), mMasterPort);
		if (ok) {
			break;
		}
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));
		logInfo("Connecting to %s:%d...", mMasterIp.c_str(), mMasterPort);
	}
	
	try
	{
		mpSocketToMasterClient->connect(mMasterIp.c_str(), mMasterPort);
	}
	catch (const std::exception&)
	{
		logError("Connecting to %s:%d...", mMasterIp.c_str(), mMasterPort);
	}
	
}

void MasterClient::onTimer(int ms)
{
	if (mpSocketToMasterClient == nullptr)
	{
		mReconnectCooldown -= ms;
		if (mReconnectCooldown <= 0)
		{
			// try reconnect
			mReconnectCooldown = 1000 * ReconnectSeconds;
			reconnect();
		}

		return;
	}

	if (mpSocketToMasterClient != nullptr)
	{
		mpSocketToMasterClient->onTimer();
	}

	//mActionExecuter.onTimer(ms);

	OnTimerMonitor(ms);

	//if (mProcess == nullptr)
	//{
	//	return;
	//}

	//if (mProcess->finished())
	//{
	//	mProcess = nullptr;
	//	setStatus(Coordinator::ENodeStatus_Free);
	//	return;
	//}

	//mProcess->onTimer(ms);
}
bool MasterClient::isRunning() {
	return mbRunning;
}
void MasterClient::close()
{
	logInfo("DaemonClient::close");
	mMessageRouter.clear();

	//mActionExecuter.clear();

	//if (mProcess != nullptr)
	//{
	//	mProcess->close();
	//	mProcess = nullptr;
	//}

	if (mpSocketToMasterClient != nullptr)
	{
		mpSocketToMasterClient->close(nullptr);
		mpSocketToMasterClient = nullptr;
	}

	mpConfig = nullptr;

	mMasterIp.clear();

	zeroMembers();
}

void MasterClient::onConnected()
{
	logInfo("Connected to master server!");
	Send2MasterRegister(Master::EMasterNodeTypeAgent, "","","");
}


void MasterClient::onDisconnected()
{
	logInfo("Disconnected from server!");


	if (mpSocketToMasterClient != nullptr)
	{
		mpSocketToMasterClient->close("Disconnected from server!");
		mpSocketToMasterClient = nullptr;
	}

	mReconnectCooldown = 1000 * ReconnectSeconds;
}

void MasterClient::onMessage(cybertron::Message& msg)
{
	//mActionExecuter.onMessage(msg);
	mMessageRouter.onMessage(msg);
}



void MasterClient::killZombieProcess()
{
#ifdef CYBERTRON_LINUX
    	logInfo("kill the zombie Process produced by bridgeIO start...");
	std::string processName = "killZombieProcess.sh";
	std::string workPath = cybertron::UtilPath::getWorkingPath();
	processName = cybertron::UtilPath::combine(workPath,processName);

	std::string cmd = "#!/bin/bash \n";
	           cmd += "PID=`pidof CybertronBridgeIO` \n";
		   cmd += "echo \"CybertronBridgeIO:$PID\" \n";
		   cmd += "echo \"pid of this script:$$\" \n";
		       cmd += "function findandkillchildren { \n";
    		   cmd += "    PIDS=`ps -ef |awk '{print $2 \" \" $3}' |grep $1 |awk '{print $1}' |grep -v $1` \n";
    		   cmd += "         echo \"enter 1111\" \n";
    		   cmd += "         echo $1 \n";
    		   cmd += "         echo $PIDS\n";
    		   cmd += "         echo \"enter 2222\" \n";
		       cmd += "    for var in $PIDS \n";
		       cmd += "    do \n";
		       cmd += "        findandkillchildren $var \n";
		       cmd += "    done \n";
			   cmd += "         echo \"will kill process $1\"\n";
		       cmd += "    sleep 1 \n";
		       cmd += "        if [ $1 == $PID ] \n";
		       cmd += "            then \n";
		       cmd += "            echo \"exit1 sucessful $1\" \n";
		       cmd += "            exit 0 \n";
		       cmd += "        fi \n";
		       cmd += "        kill proccess '$1' \n";
		       cmd += "        echo \"kill proccess $1 ok\" \n";
			   cmd += "}\n";
		       cmd += "findandkillchildren $PID \n";

	std::cout<<cmd<<std::endl;
	ofstream os;
	os.open(processName.c_str());
	os<<cmd;
	os.close();
	system("chmod +x killZombieProcess.sh");
	pid_t pid;
	int status;

	if ((pid = fork()) < 0) {
		status = -1;
	}
	else if (pid == 0) {
		chdir(workPath.c_str());
		execl("/bin/sh", "sh", "-c", processName.c_str(), (char *)0);
		_exit(127);
	}
	else {
		auto waitpid_pid = waitpid(pid, &status, 0);
    		logInfo("kill the zombie Process produced by bridgeIO end");
		while (waitpid_pid < 0) {
			if (errno != EINTR) {
				status = -1;
				break;
			}
		}
	}
#endif	
}
void MasterClient::onFromMasterNodeRegisterRet(cybertron::Message& msg) {
	//登录master返回后，同步worknode节点
	logInfo("[AgentFromMaster]onFromMasterNodeRegisterRet register master is sucessful :%s", theApp->getAppInfo().mAppId.c_str());
	WorkNodeManger::GetInstance().SyncWorkNodeListToMaster();
	

}
void MasterClient::onFromMasterCommand2Agent(cybertron::Message& msg) {
	Master::ToMasterSend2AgentCommand req;
	if (!msg.toProtobuf(req)) {
		close();
		return;
	}
	Master::SubCommandHeader  header = req.header();
	switch (header.fromtype())
	{
	case Common::EAgentNode:
		processCommandToAgent(msg);
	case Common::EWorkNode:
		processCommandToWork(msg);

	default:
		break;
	}
	logInfo("[AgentFromMaster]onFromMasterCommand2Agent command id :%d", header.subcommandid());
}

void MasterClient::onFromMasterGetAgentHardwareInfo(cybertron::Message& msg) {
	logInfo("onFromMasterGetAgentHardwareInfo");
	Master::GetAgentHardwareInfoFromCommander req;
	if (!msg.toProtobuf(req)) {
		close();
		return;
	}

	Master::GetAgentHardwareInfoFromRetCommander hardwareInfo;
	hardwareInfo.set_toid(req.fromid());
	hardwareInfo.set_errorcode(Common::ESimOneErrorCode::ESimOneOK);

	ComputerEnv::CpuEnvInfo cpuEnvInfo;
	mComputerEnv->GetInstance().GetCpuEnvInfo(cpuEnvInfo);

	ComputerEnv::MemoryEnvInfo memoryEnvInfo;
	mComputerEnv->GetInstance().GetMemoryEnvInfo(memoryEnvInfo);

	ComputerEnv::DeviceIPInfos deviceEnvInfos;
	mComputerEnv->GetInstance().GetIPConfigEnvInfo(deviceEnvInfos);

	ComputerEnv::DiskInfos diskInfos;
	mComputerEnv->GetInstance().GetDiskInfo(diskInfos);

	ComputerEnv::DisplayInfos displayInfos;
	mComputerEnv->GetInstance().GetDisplayInfos(displayInfos);

	Common::SimOneSystemInfo *systemInfo = hardwareInfo.mutable_hardwareinfo();
	systemInfo->mutable_cpuinfo()->set_mhz(cpuEnvInfo.MHZ);
	systemInfo->mutable_cpuinfo()->set_processor(cpuEnvInfo.Processor);
	systemInfo->mutable_cpuinfo()->set_cpuname("");

#ifdef CYBERTRON_WIN
	systemInfo->mutable_systeminfo()->set_systeminfo("Windows");
#else
	systemInfo->mutable_systeminfo()->set_systeminfo("Linux");
#endif	
	for (int i = 0; i < deviceEnvInfos.items.size(); i++) {
		auto deviceIPInfo = systemInfo->add_deviceiplist();
		deviceIPInfo->set_ip(deviceEnvInfos.items[i].ip);
		deviceIPInfo->set_mac(deviceEnvInfos.items[i].mac);
		deviceIPInfo->set_name(deviceEnvInfos.items[i].name);
		deviceIPInfo->set_subnetmask(deviceEnvInfos.items[i].subnetMask);
	}

	for (int i = 0; i < diskInfos.items.size(); i++) {
		auto diskinfo = systemInfo->add_diskinfos();
		diskinfo->set_capacity(diskInfos.items[i].capacity);
		diskinfo->set_free(diskInfos.items[i].free);
		diskinfo->set_name(diskInfos.items[i].name);
	}

	systemInfo->mutable_memoryinfo()->set_memfree(memoryEnvInfo.MemFree);
	systemInfo->mutable_memoryinfo()->set_memtotal(memoryEnvInfo.MemTotal);

	for (int i = 0; i < displayInfos.items.size(); i++) {
		auto displayInfo = systemInfo->add_displayinfos();
		displayInfo->set_displayname(displayInfos.items[i].displayName);
		displayInfo->set_displayid(displayInfos.items[i].displayId);
		displayInfo->set_resolutionwidth(displayInfos.items[i].resolutionWidth);
		displayInfo->set_resolutionheight(displayInfos.items[i].resolutionHeight);
		displayInfo->set_ishomescreen(displayInfos.items[i].isHomeScreen);
	}

	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::EGetAgentHardwareInfoFromRetCommander, hardwareInfo);
		}
	}
}
void MasterClient::processCommandToAgent(cybertron::Message & msg){
	Master::ToMasterSend2AgentCommand req;
	if (!msg.toProtobuf(req)) {
		close();
		return;
	}
	Master::SubCommandHeader  header = req.header();
	if (header.subcommandid() == Common::ESubCommandIDRefreshWorkNodeList) {
		//TheApp theapp;
		theApp->refreshWorkNodeList();
		Master::ToMasterSend2AgentCommandRet ret;
		ret.mutable_header()->set_id(header.id());
		ret.mutable_header()->set_fromid(header.toid());
		ret.mutable_header()->set_fromtype(header.totype());
		ret.mutable_header()->set_toid(header.fromid());
		ret.mutable_header()->set_totype(header.fromtype());
		ret.set_errorcode(Common::ESimOneOK);

		if (mpSocketToMasterClient != nullptr) {
			if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
				mpSocketToMasterClient->send(Master::ECommand2AgentFromRetCommander, ret);
			}
		}
	}
}

void MasterClient::processCommandToWork(cybertron::Message & msg){
	Master::ToMasterSend2AgentCommand req;
	if (!msg.toProtobuf(req)) {
		close();
		return;
	}
	Master::SubCommandHeader  header = req.header();
	WorkNodeManger::GetInstance().SendCommandToWorkNode(header.fromid(), header.subcommandid(), (char*)&(req.buffer()));
}
void MasterClient::onFromMasterTaskReadyRunning(cybertron::Message& msg) {
	Master::TaskReadyRunning data;

	if (!msg.toProtobuf(data))
	{
		return;
	}
	string taskId = data.taskid();

	TaskManager::GetInstance().setTaskState(taskId, Common::ETaskState_Running);
	WorkNodeManger::GetInstance().BroadcastTaskRunningToWorkNode(taskId);
}
void MasterClient::onFromMasterStartTask(cybertron::Message& msg) {

	Master::TaskStartFromCommander start;

	if (!msg.toProtobuf(start))
	{
		return;
	}
	string taskId = start.taskid();
	SimOneLicense license;
	unsigned long ret = 0;
	if (license.IsUserDog()) {
		ret = license.CheckDog();
	}

	Common::ESimOneErrorCode errorCode = Common::ESimOneOK;

	if (ret != 0) {
		logError("dog check failed error code 0x%x", ret);
		errorCode = Common::ESimOneDogCommonError;
		Send2MasterTaskStartRetFromCommander(start.taskid(), errorCode, "");
		return;
	}
	
	if (!TaskManager::GetInstance().addTask(taskId, &start)) {
		errorCode = Common::ESimOneTaskRepeat;
		Send2MasterTaskStartRetFromCommander(start.taskid(), errorCode, "");
		return;
	}

	Send2MasterTaskStartRetFromCommander(start.taskid(), errorCode, "");
	

}
void MasterClient::onFromMasterStopTask(cybertron::Message& msg) {

	Master::TaskStopFromCommander data;

	if (!msg.toProtobuf(data))
	{
		return;
	}
	string taskId = data.taskid();
	Common::ETaskEndReason reason = data.reason();
	logInfo("[AgentFromMaster]onFromMasterStopTask:task id %s reason:%d", taskId.c_str(), reason);
	TaskManager::GetInstance().setTaskState(taskId, Common::ETaskState_Ending);
	

	WorkNodeManger::GetInstance().BroadcastWorkNodeStopToWorkNode(taskId);

	WorkNodeManger::GetInstance().BroadcastTaskStopToWorkNode(taskId, reason);
	
}
void MasterClient::onFromMasterStartWorkNode(cybertron::Message& msg) {
	//start work,start work porcess
	Master::WorkNodeStartFromMaster data;

	if (!msg.toProtobuf(data))
	{
		return;
	}
	string taskId = data.taskid();
	Master::AllocNodeWorkItem* pWorkItem = data.mutable_workitem();
	string workNodeId =pWorkItem->worknodeid();
	Common::EWorkNodeType workType = pWorkItem->worktype();
	string name = UtilStateHelper::GetInstance().GetWorkNodeName(workType);
	WorkNodeManger::GetInstance().SetWorkNodeTaskId(workNodeId, taskId);

	string agentId = pWorkItem->agentid();
	if (agentId.size() == 0) {
		logError("[AgentFromMaster]onFromMasterStartWorkNode agentId empty task id:%s work id:%s work type:%s agent id:%s", taskId.c_str(), workNodeId.c_str(), name.c_str(), agentId.c_str());
		return;
	}
	//TODO only debug
	/*if (workType == Common::EWorkNodeType_CybertronVR) {
		WorkNodeManger::GetInstance().SetWorkNodeState(workNodeId, Common::EWorkNodeStateStarting);
		Send2MasterWorkNodeStartRetFromCommander(taskId, workNodeId, workType, Common::ESimOneOK, "Start Process Successful");
		return;
	}*/
	Master::ConfigWorkItem configItem;
	string commandline = "";
	if (TaskManager::GetInstance().getTaskWorkConfigItem(data.taskid(), workNodeId, configItem)) {
		commandline = configItem.commandline();
	}
	if (!WorkNodeManger::GetInstance().startProcess(workNodeId,workType, commandline)) {
		Send2MasterWorkNodeStartRetFromCommander(taskId, workNodeId, workType, Common::ESimOneStartProcessError, "Start Process Failed");
		logError("[AgentFromMaster]onFromMasterStartWorkNode start process failed task id:%s work id:%s work type:%s agent id:%s", taskId.c_str(), workNodeId.c_str(), name.c_str(), agentId.c_str());
		return;
	}
	WorkNodeManger::GetInstance().SetWorkNodeState(workNodeId,Common::EWorkNodeStateStarting);
	Send2MasterWorkNodeStartRetFromCommander(taskId, workNodeId, workType, Common::ESimOneOK, "Start Process Successful");
	
	//logInfo("[AgentFromMaster]onFromMasterStartWorkNode task id:%s work id:%s work type:%s agent id:%s", taskId.c_str(), workNodeId.c_str(), name.c_str(), agentId.c_str());
}
void MasterClient::onFromTaskStateChange(cybertron::Message& msg) {
	Master::TaskStateChange data;
	if (!msg.toProtobuf(data))
	{
		return;
	}

	TaskManager::GetInstance().setTaskState(data.taskid(), data.taskstate());
	return;
}

void MasterClient::onFromMasterStopWorkNode(cybertron::Message& msg) {
	//stop work

	Master::WorkNodeStopFromMaster data;

	if (!msg.toProtobuf(data))
	{
		return;
	}
	string workNodeId = data.worknodeid();
	WorkNodeManger::GetInstance().SendWorkNodeStopToWorkNode(workNodeId);

}
void MasterClient::onFromMasterSyncWorkNodeDynamicConfig(cybertron::Message& msg) {
	Common::SyncWorkNodeDynamicConfig req;
	if (!msg.toProtobuf(req))
	{
		return;
	}
	
	string name = UtilStateHelper::GetInstance().GetWorkNodeName(req.worknodetype());
	string workId = req.worknodeid();
	
	logInfo("[AgentFromMaster]onFromMasterSyncWorkNodeDynamicConfig[%s] work id:%s task id %s", name.c_str(), workId.c_str(), req.taskid().c_str());
	TaskManager::GetInstance().addSyncWorkNodeDynamicConfig(&req);
	
}
void MasterClient::onFromMasterStartScript(cybertron::Message& msg) {
	logInfo("onFromMasterStartScript");
	Master::StartScriptConfig data;
	if (!msg.toProtobuf(data))
	{
		return;
	}
	std::string scriptPath = UtilPath::getExecutablePath();
	std::string scriptFile = UtilPath::combine(scriptPath, data.scriptname());
	if (scriptFile.empty()) {
		return;
	}
#ifdef CYBERTRON_LINUX
#else
	std::string scriptContent = data.scriptcontent();
	string fileName = scriptFile + ".bat";
	logInfo("[AgentFromMaster]onFromMasterStartScript file:%s", fileName.c_str());
	FILE* fp = fopen(fileName.c_str(), "w");
	fwrite(scriptContent.c_str(), scriptContent.size(), 1, fp);
	fclose(fp);
	std::vector<std::string> params;
	std::vector<std::string> envs;
	ProcessHandle process;
	bool isService = theApp->isService();
	if (!UtilProcess::startWindowsBat(fileName, scriptPath, params, process, envs, isService)) {
		logInfo("Can not start script is:%s", scriptFile.c_str());
	}
	if (data.iscreateshortcut()) {
		//UtilWin32::GetInstance().CreatLinkToDeskTop(scriptPath, data.scriptname());
	}
	if (data.ispowerboot()) {
		//UtilWin32::GetInstance().CreatLinkToStartMenu(scriptPath, data.scriptname());
	}
#endif
}

void convertUnCharToStr(char* str, unsigned char* UnChar, int ucLen)
{
	int i = 0;
	for (i = 0; i < ucLen; i++){
		sprintf(str + i * 2, "%02x", UnChar[i]);
	}
}
void MasterClient::onFromMasterGetDongleInfo(cybertron::Message& msg) {
	logInfo("onFromMasterGetDongleInfo");
	Master::GetDongleInfoFromAgent data;
	if (!msg.toProtobuf(data)){
		return;
	}

	SimOneLicense license;
	unsigned long dogRetCode = 0;
	bool isencrypted = false;
	bool isUserDog = license.IsUserDog();
	if (isUserDog) {
		isencrypted = true;
		dogRetCode = license.CheckDog();
	}
	
	DongleInfo* dongleInfo = license.getDongleInfo();
	DONGLE_INFO* cardDongleInfo = license.getCardDongleInfo();
	auto hid = cardDongleInfo->m_HID;
	unsigned long deadTime = license.getDDeadTime();
	char danggleId[64] = {0};
	convertUnCharToStr(danggleId, cardDongleInfo->m_HID, sizeof(cardDongleInfo->m_HID));

	Master::GetDongleInfoFromAgentRet ret;
	ret.set_fromid(data.toid());
	ret.set_toid(data.fromid());
	ret.set_errordescribe("errordescribe");
	ret.set_agentid(data.toid());
	ret.set_isencrypted(isencrypted);
	ret.set_dongleid(danggleId);
	ret.set_channelname(dongleInfo->channel_name);
	ret.set_producttype(dongleInfo->product_type);
	ret.set_version(dongleInfo->version);
	ret.set_createtime(dongleInfo->create_time);
	ret.set_deadtime(deadTime);
	ret.set_branchname(dongleInfo->branch_name);
	if (dogRetCode == 0) {
		ret.set_errorcode(Common::ESimOneOK);
	}
	else {
		ret.set_errorcode(Common::ESimOneDogCommonError);
	}
	ret.set_paramcode(dogRetCode);
	//errorCode
	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::EGetDongleInfoFromAgentRet, ret);
		}
	}
}

void MasterClient::onSubCommandPauseToWorkNode(std::string workNodeId){
}
void MasterClient::onSubCommandPlayWorkNode(std::string workNodeId){
}
void MasterClient::Send2MasterRegister(Master::MasterNodeType tpye, string version, string desc, string data) {
	Master::NodeInfoAtMaster info;
	string appId = theApp->getAppInfo().mAppId;

	info.set_type(tpye);
	info.set_nodeid(appId);
	info.set_version(version);
	info.set_desc(desc);
	info.set_data(data);
	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::ENodeRegisterAtMaster, info);
		}
	}
}
void MasterClient::Send2MasterWorkNodeStartRetFromCommander(string taskId, string workNodeId, Common::EWorkNodeType workType, Common::ESimOneErrorCode errorCode, string message) {
	Master::WorkNodeStartRetFromMaster info;

	
	info.set_taskid(taskId);
	info.set_worktype(workType);
	info.set_worknodeid(workNodeId);
	info.set_errorcode(errorCode);
	info.set_message(message);
	//info.set_agentid(agentId);
	
	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::EWorkNodeStartRetFromMaster, info);
		}
	}
}
void MasterClient::Send2MasterTaskStartRetFromCommander(string taskId, Common::ESimOneErrorCode errorCode, string message) {
	Master::TaskStartRetFromCommander data;
	string agentId = theApp->getAppInfo().mAppId;
	data.set_taskid(taskId);
	data.set_errorcode(errorCode);
	data.set_message(message);
	data.set_agentid(agentId);
	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::ETaskStartRetFromCommander, data);
		}
	}
}
void MasterClient::Send2MasterSyncWorkNodeStatus(string taskId, string workNodeId, Common::EWorkNodeType workType, Common::EWorkNodeStatus workStatus) {

	Master::SyncWorkNodeStatusFromAgent data;
	string appId = theApp->getAppInfo().mAppId;
	data.set_agentid(appId);
	data.set_taskid(taskId);
	data.set_worknodeid(workNodeId);
	data.set_worktype(workType);
	data.set_status(workStatus);
	
	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::ESyncWorkNodeStatusFromAgent, data);
		}
	}
}
void MasterClient::Send2MasterSyncWorkNodeState(string taskId, string workNodeId, Common::EWorkNodeType workType, Common::EWorkNodeState worksState) {
	Master::SyncWorkNodeStateFromAgent data;
	string appId = theApp->getAppInfo().mAppId;
	data.set_agentid(appId);
	data.set_taskid(taskId);
	data.set_worknodeid(workNodeId);
	data.set_worktype(workType);
	data.set_workstate(worksState);

	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::ESyncWorkNodeStateFromAgent, data);
		}
	}
}

void MasterClient::Send2MasterSyncWorkNodeList(WorkNodeInfoList& workNodeList) {
	
	Master::SyncWorkNodeListFromAgent data;
	string appId = theApp->getAppInfo().mAppId;
	data.set_agentid(appId);
	size_t length = workNodeList.size();
	WorkNodeInfoList ScalableWorkNodeList;
	for (size_t i = 0; i < length; i++)
	{
		Common::SimOneWork* pWorkNode = data.add_worknodelist();
		pWorkNode->set_type(workNodeList[i]->type);

		pWorkNode->set_workname(UtilStateHelper::GetInstance().GetWorkNodeName(workNodeList[i]->type));
		pWorkNode->set_worknodeid(workNodeList[i]->workNodeId);
		pWorkNode->set_status(workNodeList[i]->status);
		pWorkNode->set_state(workNodeList[i]->state);
		if (int(workNodeList[i]->type) >= 3000) {
			ScalableWorkNodeList.push_back(workNodeList[i]);
		}
		
		logInfo("Sync Work Node To Master ===> type:%s work id:%s status:%d state:%d",
			UtilStateHelper::GetInstance().GetWorkNodeName(workNodeList[i]->type).c_str(), workNodeList[i]->workNodeId.c_str(), workNodeList[i]->status, workNodeList[i]->state);
	}

	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			logInfo("Sync Work Node count:%d ", workNodeList.size());
			mpSocketToMasterClient->send(Master::ESyncWorkNodeListFromAgent, data);
		}
	}
	length = ScalableWorkNodeList.size();
	for (size_t i = 0; i < length; i++) {
		string workName = UtilStateHelper::GetInstance().GetWorkNodeName(ScalableWorkNodeList[i]->type);
		Send2MasterSyncScalableNodeInfo(ScalableWorkNodeList[i]->workNodeId, workName, ScalableWorkNodeList[i]->type);
	}

}
void MasterClient::Send2MasterSyncScalableNodeInfo(string workId, string workname, Common::EWorkNodeType workType) {
	UtilStateHelper::WorkTypeList typeList;
	if (!UtilStateHelper::GetInstance().GetScalableWorkNodeInfo(workType, typeList)) {
		return;
	}
	Master::SyncScalableNodeInfoFromAgent data;
	string appId = theApp->getAppInfo().mAppId;
	data.set_agentid(appId);
	data.set_workid(workId);
	data.set_workname(workname);
	size_t length = typeList.size();
	for (size_t i = 0; i < length; i++)
	{

		Common::EWorkNodeType realWorkType = typeList[i];
		data.add_worktypelist(realWorkType);
		string xx = UtilStateHelper::GetInstance().GetWorkNodeName(workType);
		logInfo("SyncScalable To Master ===>src type:%s dst type:%s work id:%s ",
			UtilStateHelper::GetInstance().GetWorkNodeName(workType).c_str(),UtilStateHelper::GetInstance().GetWorkNodeName(realWorkType).c_str(), workId.c_str());
	}

	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::ESyncScalableNodeInfoFromAgent, data);
		}
	}
	return;
}
void MasterClient::Send2MasterSycnWorkNodeDynamicConfig(Common::SyncWorkNodeDynamicConfig* pConfig) {
	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Common::ESyncWorkNodeDynamicConfig, *pConfig);
		}
	}
}

void MasterClient::Send2MasterStopTask(string from, string taskId, string workNodeId, Common::EWorkNodeType workType, Common::ETaskEndReason reason) {
	Master::StopTaskFromAgent data;
	string appId = theApp->getAppInfo().mAppId;
	data.set_agentid(appId);
	data.set_taskid(taskId);
	data.set_workid(workNodeId);
	data.set_worktype(workType);
	data.set_reason(reason);

	logWarning("[From===>%s]:Stop task [%s],work id :%s", from.c_str(), UtilStateHelper::GetInstance().GetWorkNodeName(workType).c_str(),workNodeId.c_str());

	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::EStopTaskFromAgent, data);
		}
	}
}

void MasterClient::Send2MasterCommanderRet(Master::SubCommandHeader header, const char * pBuffer, int length){
	Master::ToMasterSend2AgentCommandRet data;
	data.mutable_header()->set_id(header.id());
	data.mutable_header()->set_fromid(header.toid());
	data.mutable_header()->set_fromtype(header.totype());
	data.mutable_header()->set_toid(header.fromid());
	data.mutable_header()->set_totype(header.fromtype());

	data.set_errorcode(Common::ESimOneErrorCode::ESimOneOK);
	std::string *pData = data.mutable_buffer();
	pData->resize(length);
	if (pData->size() > 0)
	{
		memcpy(&(pData->operator[](0)), pBuffer, length);
	}

	if (mpSocketToMasterClient != nullptr) {
		if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
			mpSocketToMasterClient->send(Master::ECommand2AgentFromRetCommander, data);
		}
	}
}
void MasterClient::OnTimerMonitor(int ms) {
	static int last_past_ms = 0;
	last_past_ms += ms;

	if (last_past_ms < 1000) {
		return;
	}
	last_past_ms = 0;

	int proc_cpu = 0;
	int proc_memory = 0;
	
	int sys_cpu = UtilSysRes::sysCpuUsage();
	int sys_memory = UtilSysRes::sysMemUsage();


	//if (mProcess == nullptr || mProcess->finished())
	//{
	//	proc_cpu = -1;
	//	proc_memory = -1;
	//}
	//else {
	//	mProcess->getProcRes(proc_cpu, proc_memory);
	//}

	//Coordinator::FromDaemonResMonitor stat;
	//stat.set_syscpuusage(sys_cpu);
	//stat.set_sysmemusage(sys_memory);
	//stat.set_proccpuusage(proc_cpu);
	//stat.set_procmemusage(proc_memory);

	//if (mpSocketToMasterClient != nullptr) {
	//	if (mpSocketToMasterClient->getStatus() == ESocketStatus_Connected) {
	//		mpSocketToMasterClient->send(Coordinator::EFromDaemonResMonitor, stat);
	//	}
	//	
	//}
}
